# -*- coding: utf-8 -*-
"""
Implementation of the trendy bot

A Trends finding robot
"""

__authors__ = ['fccoelho@gmail.com (Flavio Coelho)', 'ogcruz@gmail.com (Oswaldo Cruz)']

import logging

from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.api import images


from waveapi import events
from waveapi import element
from waveapi import robot
from waveapi import appengine_robot_runner

from GChartWrapper import Line, Text
from csv import DictReader
import re #Let's use regular expressions to look for trend words
from collections import defaultdict

##=====Models==========
class Topic(db.Model):
    '''Class to count topic searches'''
    topic = db.StringProperty(required=True)
    frequency = db.IntegerProperty(default=1)
    comparisons = db.StringListProperty()
    
class Comparison(db.Model):
    topics = db.StringListProperty()
    frequency = db.IntegerProperty(default=1)
    
    

def OnParticipantsChanged(properties, context):
    """Invoked when any participants have been added/removed."""
    added = properties['participantsAdded']
    for p in added:
        Notify(context)

def OnRobotAdded(properties, context):
    """Invoked when the robot has been added."""
    root_wavelet = context.GetRootWavelet()
    root_wavelet.CreateBlip().GetDocument().SetText("I'm alive!")

def Notify(context):
    root_wavelet = context.GetRootWavelet()
    root_wavelet.CreateBlip().GetDocument().SetText('Hi everybody! \nTo get the latest trend on topics, just type "~~topic1,topic2;" \nand see it replace by a trend graph with up to four topics!\n Do not forget the ending ";"')

def OnBlipSubmitted(event, wlet):
    """Invoked everytime a blip is submitted"""
    
    blip = event.blip
    if not blip: 
	return
    for w,p in parse_contents(blip).iteritems():
        #trimg = document.Image(create_chart(w), caption=w)
        mkp_img = element.Image(url=Text('darkred',11,'h','red','b',w).url)
        #blip.GetDocument().AppendElement(mkp_img)
        blip.append(mkp_img)
        trgdgt = trend_gadget(w)
        #blip.GetDocument().AppendElement(trgdgt)
        blip.append(trgdgt)
    
def store_data(topics):
    for t in topics:
        q = Topic.all().filter("topic = ", t)
        r = q.count()
        if r == 0:
            try:
                T = Topic(topic=t,frequency=1,comparisons=[i for i in topics if i!=t])
                T.put()
            except:
                logging.debug("failed on topic: %s"%t)
        else:
            T = q.get()
            T.frequency += 1
            for c in topics:
                if c == t: continue
                if c not in T.comparisons:
                    T.comparisons.append(c)
            T.put()
    q2 = Comparison.all()
    for t in topics:
        q3 = q2.filter('topics = ',t)
        if q3.count() == 0:
            C = Comparison(topics=topics)
            C.put()
        else:
            C = q3.get()
            C.frequency += 1
            C.put()

def create_chart(markup):
    """
    creates the GChart url and returns it
    data : dictionary of words-->series
    tlabs : list of strings for use as x axis labels
    """
    data,tlabs = get_trends(markup)
    if not data:
        return Text('darkred',12,'h','red','b',"sorry, no trend found.").url
    colors = ['blue','red','black','green']
    mv = max([max(i) for i in data.values()])
    G = Line(data.values())
    G.scale(0,mv)
    G.color(*colors[:len(data)])
    G.legend(data.keys())
    G.axes('xy')
    G.axes.label(0,tlabs[0],tlabs[-1])
    G.axes.label(1,0,mv)
    return G.url

def trend_gadget(markup):
    """
    Returns a trend gadget for the given markup
    """
    markup = markup.strip().strip('.').strip('~').strip(";")
    tl = markup.split(',')
    store_data([i.strip() for i in tl])
    gadurl = "http://trendy-robot.appspot.com/gadget.xml?markup=%s"%markup
    gdgt = element.Gadget(gadurl)
    
    return gdgt
    
def parse_contents(blip):
    """
    Parse the contents of a blip returning a dictionary of {words:positions}
    """
    #pattern = re.compile("~~([\w\s]*[\W]{1}){1,4}[\.\s]{1}") #old pattern
    pattern = re.compile("~~([^(,;)]{2,16})(,[^(,;)]+){0,3}[;\n?$]")
    contents = blip.text
    d = {}
    off = 0 #offset of insert position after markup is removed
    for t in re.finditer(pattern,contents):
        off += t.end()-t.start()
        d[t.group(0)] = off #topic list and insertion position 
        contents = contents.replace(t.group(0), '') #remove markup
    
    blip.all().delete()
    blip.append(contents+"  ")
    return d


if __name__ == '__main__':
    logging.getLogger().setLevel(logging.DEBUG)
    trendyRobot = robot.Robot('Trendy', 
      image_url='http://trendy-robot.appspot.com/assets/icon.png',
      profile_url='http://trendy-robot.appspot.com/')
    trendyRobot.register_handler(events.WaveletParticipantsChanged, OnParticipantsChanged)
    trendyRobot.register_handler(events.WaveletSelfAdded, OnRobotAdded)
    trendyRobot.register_handler(events.BlipSubmitted, OnBlipSubmitted)

    appengine_robot_runner.run(trendyRobot,debug=True)
